﻿/*
 * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
 */

#include "BurnCtrlSle.h"
#include <QFile>
#include <QSettings>
#include <QDir>
#include <QApplication>
#include "../platform/Securec/securec.h"
#include "BurnToolCommon/diagCmdId.h"
#include "BurnToolCommon/CompatibleCmd.h"
#include "BurnToolCommon/CompatibleMss.h"
#include "DataConvertor.h"
namespace  {
    const uint32_t PACKAGE_SIZE = 128;
    const uint32_t BUFFER_SIZE_MAX = 4 * 1024;
    const uint32_t PAYLOAD_BUFFER_SIZE = 5000;
    const int TIME10000 = 10000;
    const int PARAM = 6;
    using namespace BurnCtrlSleClass;
}
BurnCtrlSle::BurnCtrlSle(QObject *parent)
    : QObject(parent),
      usbPort(new UsbPortClass::UsbPort()),
      usbthread(new MyThreadClass::MyThread()),
      isBusy(false),
      binInfoArrayIndex(0),
      mTransmitId(0),
      readBufferSize(0),
      buffer(new BYTE[BUFFER_SIZE_MAX]()),
      bufferSize(0),
      currentCmdId(0),
      otaTimer(nullptr),
      otaTimeoutCount(0),
      isStop(false),
      ms(0),
      packet(PACKAGE_SIZE),
      blockNum(1)
{
    if (buffer != nullptr && usbPort != nullptr && usbthread != nullptr) {
        ReadConfig();
        int ret = memset_s(buffer, BUFFER_SIZE_MAX, 0, BUFFER_SIZE_MAX);
        if (ret != 0) {
            qDebug() << "memset failed";
        }
        qRegisterMetaType<QVector<SleDeviceInfo>>("QVector<SleDeviceInfo>");
        usbPort->moveToThread(usbthread);
        connect(usbthread, &QThread::finished, usbPort, &QObject::deleteLater);
        connect(this, &BurnCtrlSle::SignalReadThread, usbPort, &UsbPortClass::UsbPort::ReadThread);
        connect(usbPort, &UsbPortClass::UsbPort::SignalReadData, this, &BurnCtrlSle::SlotReadData);
        usbthread->start();
    }
}

BurnCtrlSle::~BurnCtrlSle()
{
    if (buffer != nullptr) {
        delete [] buffer;
        buffer = nullptr;
    }

    if (usbPort != nullptr) {
        delete usbPort;
        usbPort = nullptr;
    }

    if (usbthread != nullptr) {
        delete usbthread;
        usbthread = nullptr;
    }

    if (otaTimer != nullptr) {
        delete otaTimer;
        otaTimer = nullptr;
    }
}

void BurnCtrlSle::ReadConfig()
{
    QString path = Global::GetAppConfigPath();
    path += "\\config_" + Global::ChipTypeIdToString(Global::currentChipTypeId);
    QSettings cfg(path  + "\\config.ini", QSettings::IniFormat);

    ms = cfg.value("DFU_CONFIG/TIME_INTERVAL").toUInt();
    packet = cfg.value("DFU_CONFIG/PACKET_SIZE").toUInt();
    blockNum = cfg.value("DFU_CONFIG/PACKET_BLOCK_NUM").toUInt();
}

void BurnCtrlSle::SetDeviceInterface(const QString &mDeviceInterface)
{
    this->deviceInterface = mDeviceInterface;
}

void BurnCtrlSle::SlotSendMsg(long int msgId, WPARAM wParam, LPARAM lParam)
{
    if (msgId == static_cast<long int>(SleThreadMsg::SLE_THREAD_MSG_OPEN)) {
        OpenDevice();
    } else if (msgId == static_cast<long int>(SleThreadMsg::SLE_THREAD_MSG_CLOSE)) {
        CloseDevice();
    } else if (msgId == static_cast<long int>(SleThreadMsg::SLE_THREAD_MSG_CONNECT)) {
        ConnectServer(wParam, lParam);
    } else if (msgId == static_cast<long int>(SleThreadMsg::SLE_THREAD_MSG_START_BURN)) {
        StartBurn();
    } else if (msgId == static_cast<long int>(SleThreadMsg::SLE_THREAD_MSG_STOP_SEARCH)) {
        StopSearch();
    } else if (msgId == static_cast<long int>(SleThreadMsg::SLE_THREAD_MSG_DISCONNECT)) {
        DisconnectServer(wParam, lParam);
    } else if (msgId == static_cast<long int>(SleThreadMsg::SLE_THREAD_MSG_STOP_BURN)) {
        StopBurn();
    }
}

void BurnCtrlSle::OpenDevice()
{
    bool ret = false;
    if (usbPort != nullptr) {
        ret = usbPort->OpenDevice(deviceInterface.toLatin1().data(), TRUE);
    }
    emit SignalReadThread();
    if (!ret) {
        emit SignalOpenDeviceFail();
        QString str = tr("Device opened unsuccessfully!\n");
        OutputString(str);
        Close(ERR_COM_INVALID);
    } else {
        QString str = tr("Device opened successfully!\n");
        OutputString(str);
        EnableSle();
    }
}

void BurnCtrlSle::CloseDevice() const
{
    if (usbPort != nullptr) {
        usbPort->CloseDevice();
    }
}

void BurnCtrlSle::EnableSle()
{
    usbPacket.SetData(nullptr, 0);
    uint8_t *payloadPacket = usbPacket.GetPayloadPack(0x01, 0x01);
    uint16_t payloadPacketLen = usbPacket.GetPayloadBufferSize();
    if (usbPort != nullptr) {
        usbPort->UsbThread(payloadPacket, payloadPacketLen);
    }
}

void BurnCtrlSle::DisableSle()
{
    usbPacket.SetData(nullptr, 0);
    uint8_t *payloadPacket = usbPacket.GetPayloadPack(0x01, 0x02);
    uint16_t payloadPacketLen = usbPacket.GetPayloadBufferSize();
    if (usbPort != nullptr) {
        usbPort->UsbThread(payloadPacket, payloadPacketLen);
    }
}

void BurnCtrlSle::StartSearch()
{
    usbPacket.SetData(nullptr, 0);
    uint8_t *payloadPacket = usbPacket.GetPayloadPack(0x01, 0x0D);
    uint16_t payloadPacketLen = usbPacket.GetPayloadBufferSize();
    if (usbPort != nullptr) {
        usbPort->UsbThread(payloadPacket, payloadPacketLen);
    }
}

void BurnCtrlSle::StopSearch()
{
    usbPacket.SetData(nullptr, 0);
    uint8_t *payloadPacket = usbPacket.GetPayloadPack(0x01, 0x0E);
    uint16_t payloadPacketLen = usbPacket.GetPayloadBufferSize();
    if (usbPort != nullptr) {
        usbPort->UsbThread(payloadPacket, payloadPacketLen);
    }
}

void BurnCtrlSle::ConnectServer(WPARAM wParam, LPARAM lParam)
{
    SleDeviceInfo *mSleDeviceInfo = reinterpret_cast<SleDeviceInfo *>(wParam);
    if (mSleDeviceInfo == nullptr || lParam == 0) {
        return;
    }
    usbPacket.SetTlv(0x01, &(mSleDeviceInfo->addrType), 1);
    usbPacket.SetTlv(0x02, mSleDeviceInfo->addr, lParam);
    uint8_t *payloadPacket = usbPacket.GetPayloadPack(0x02, 0x01);
    if (usbPort != nullptr) {
        usbPort->UsbThread(payloadPacket, usbPacket.GetPayloadBufferSize());
    }
}

void BurnCtrlSle::DisconnectServer(WPARAM wParam, LPARAM lParam)
{
    SleDeviceInfo *mSleDeviceInfo = reinterpret_cast<SleDeviceInfo *>(wParam);
    if (mSleDeviceInfo == nullptr || lParam == 0) {
        return;
    }
    usbPacket.SetTlv(0x01, &(mSleDeviceInfo->addrType), 1);
    usbPacket.SetTlv(0x02, mSleDeviceInfo->addr, lParam);
    uint8_t *payloadPacket = usbPacket.GetPayloadPack(0x02, 0x02);
    if (usbPort != nullptr) {
        usbPort->UsbThread(payloadPacket, usbPacket.GetPayloadBufferSize());
    }
}

void BurnCtrlSle::StartBurn()
{
    binInfoArrayIndex = 0;
    uint16_t type = static_cast<uint16_t>(UpgradeTypeT::UPG_INFO_TYPE_PERMIT);
    isStop = false;
    UpgGetInfo(type);
}

void BurnCtrlSle::StopBurn()
{
    DIAG_CMD_ID_CONVERT_PACKET_ENCAPSULATION_FACTORY factory;
    PBYTE pram = nullptr;
    factory.GetCmdIdPacketClass()->SetData(pram, 0);
    PBYTE tlvData = factory.GetCmdIdPacketClass()->TLVPacket(0x01);
    otaTimer->stop();
    binInfoArray.clear();
    SendFrame(DIAG_CMD_ID_UPGRADE_STOP, tlvData, factory.GetCmdIdPacketClass()->GetBufferSize());
}

void BurnCtrlSle::UpgGetInfo(uint16_t type)
{
    DIAG_CMD_ID_CONVERT_PACKET_ENCAPSULATION_FACTORY factory;
    factory.GetCmdIdPacketClass()->SetData(reinterpret_cast<PBYTE>(&type), sizeof(uint16_t));
    PBYTE tlvData = factory.GetCmdIdPacketClass()->TLVPacket(0x01);
    SendFrame(DIAG_CMD_ID_UPGRADE_STATUS, tlvData, factory.GetCmdIdPacketClass()->GetBufferSize());
}

bool BurnCtrlSle::IsBusy() const
{
    return isBusy;
}

void BurnCtrlSle::InitBurnCmdByArray(const QMap<int, BIN_INFO> &infoArray)
{
    binInfoArray.clear();
    int i = 0;
    for (auto it = infoArray.begin(); it != infoArray.end(); it++, i++) {
        binInfoArray[i] = it.value();
    }
}

void BurnCtrlSle::SendFrame(uint32_t ulPacketId, PBYTE pucPacket, uint32_t usPacketSize)
{
    SaveBuffer(ulPacketId, pucPacket, usPacketSize);
    BurnToolCommon::MSP_DIAG_HEAD_REQ_STRU_FACTORY factory;
    BurnToolCommon::MSP_DIAG_HEAD_REQ_STRU_CLASS *pstDiagHeadReq = factory.GetItem();
    pstDiagHeadReq->SetCmdId(ulPacketId);
    pstDiagHeadReq->SetData(pucPacket, usPacketSize);
    PBYTE mBuffer = pstDiagHeadReq->GetBuffer();
    uint32_t mBufferSize = pstDiagHeadReq->GetBufferSize();
    BurnToolCommon::MSP_MUX_PACKET_HEAD_STRU_FACTORY headFactory;
    BurnToolCommon::MSP_MUX_PACKET_HEAD_STRU_CLASS *pstDiagHead = headFactory.GetItem();
    if (pstDiagHead == nullptr) {
        return;
    }
    pstDiagHead->SetData(mBuffer, mBufferSize);
    pstDiagHead->SetCtrl(0x03);
    PBYTE diagBuffer = pstDiagHead->GetBuffer();
    uint32_t diagBufferSize = pstDiagHead->GetBufferSize();
    uint8_t clientId = 0;
    uint16_t connId = 0;
    uint16_t handle = 0;
    uint8_t type = 0;
    usbPacket.SetTlv(0x01, &clientId, 1);
    usbPacket.SetTlv(0x02, reinterpret_cast<PBYTE>(&connId), sizeof (uint16_t));
    usbPacket.SetTlv(0x03, reinterpret_cast<PBYTE>(&handle), sizeof (uint16_t));
    usbPacket.SetTlv(0x04, reinterpret_cast<PBYTE>(&type), 1);
    usbPacket.SetTlv(0x05, reinterpret_cast<PBYTE>(&diagBufferSize), sizeof (uint16_t));
    usbPacket.SetTlv(0x06, reinterpret_cast<PBYTE>(diagBuffer), diagBufferSize);
    uint8_t *payloadPacket = usbPacket.GetPayloadPack(0x03, 0x07);
    if (usbPort != nullptr) {
        usbPort->SetMs(ms);
        usbPort->UsbThread(payloadPacket, usbPacket.GetPayloadBufferSize());
    }
    delete pstDiagHead;
    pstDiagHead = nullptr;
    if (ulPacketId == DIAG_CMD_ID_UPGRADE_START) {
        return;
    }
    int time = 1000;
    if (ulPacketId == DIAG_CMD_ID_UPGRADE_PREPARE) {
        time = TIME10000;
    }
    StartOTATimer(time);
}

void BurnCtrlSle::StartOTATimer(int time)
{
    if (otaTimer != nullptr) {
        delete otaTimer;
        otaTimer = nullptr;
    }
    otaTimer = new QTimer();
    if (otaTimer != nullptr) {
        connect(otaTimer, &QTimer::timeout, this, &BurnCtrlSle::SlotOtaTimeout, Qt::DirectConnection);
        otaTimer->setInterval(time);  // 1000ms超时时间
        otaTimer->start();
    }
}

void BurnCtrlSle::UpgPrepare()
{
    DIAG_CMD_ID_CONVERT_PACKET_ENCAPSULATION_FACTORY factory;
    uint32_t fileSize = DataConvertor::Str2U32DecHex(binInfoArray[binInfoArrayIndex].fileSize);
    QString str = "";
    if (binInfoArray[binInfoArrayIndex].fileName.isEmpty()) {
        str = binInfoArray[binInfoArrayIndex].path;
    } else {
        str = binInfoArray[binInfoArrayIndex].fileName;
    }
    str += tr(" start upload\n");
    OutputString(str);
    factory.GetCmdIdPacketClass()->SetData(reinterpret_cast<PBYTE>(&fileSize), sizeof(uint32_t));
    PBYTE tlvData = factory.GetCmdIdPacketClass()->TLVPacket(0x01);
    SendFrame(DIAG_CMD_ID_UPGRADE_PREPARE, tlvData, factory.GetCmdIdPacketClass()->GetBufferSize());
}

void BurnCtrlSle::UpgTransmitStart()
{
    qsrand(QTime(0, 0, 0).msecsTo(QTime::currentTime()));
    mTransmitId = 2340 + qrand() % 100; // 2340 ~ 2440 共100个随机数

    TransmitNegotiatePkt startPkt;
    startPkt.transmitId = mTransmitId;
    startPkt.srcSend = true;
    startPkt.structVer = 0;
    startPkt.reTrans = 0;
    startPkt.bitmapEnable = 0;
    startPkt.pad = 0;
    startPkt.transmitType = static_cast<uint16_t>(TransmitType::TRANSMIT_TYPE_SAVE_OTA_IMG);
    uint32_t fileSize = DataConvertor::Str2U32DecHex(binInfoArray[binInfoArrayIndex].fileSize);
    startPkt.totalSize = fileSize;
    startPkt.dataBlockNum = blockNum;
    startPkt.dataBlockSize = packet;
    startPkt.infoSize = 0;
    DIAG_CMD_ID_CONVERT_PACKET_ENCAPSULATION_FACTORY factory;
    factory.GetCmdIdPacketClass()->SetData(reinterpret_cast<PBYTE>(&startPkt), sizeof(TransmitNegotiatePkt));
    PBYTE tlvData = factory.GetCmdIdPacketClass()->TLVPacket(0x01);
    SendFrame(DIAG_CMD_ID_TRANSMIT_NEGOTION, tlvData, factory.GetCmdIdPacketClass()->GetBufferSize());
}

void BurnCtrlSle::UpgTransmitReply(QVector<TransmitDataRequestItem> items)
{
    for (auto &item : items) {
        uint32_t exceptedFileOffset = item.offset;
        uint32_t tempSize = item.size;
        QString cleanPath = QDir::cleanPath(binInfoArray[binInfoArrayIndex].path);
        if (cleanPath.isEmpty()) {
            return;
        }
        QFile file(cleanPath);
        uint32_t burnFileIndex = DataConvertor::Str2U32DecHex(binInfoArray[binInfoArrayIndex].fileIndex);
        if (!file.open(QIODevice::ReadOnly)) {
            return;
        }
        file.seek(exceptedFileOffset + burnFileIndex);
        QByteArray byteArray = file.read(tempSize);
        PBYTE mBuffer = new BYTE[tempSize]();
        if (mBuffer == nullptr) {
            return;
        }
        errno_t memcpyRet = memcpy_s(mBuffer, tempSize, byteArray.data(), tempSize);
        if (memcpyRet != EOK) {
            return;
        }
        // 分包
        int packegeCount = tempSize / packet;
        for (int i = 0; i < packegeCount; i++) {
            PostData(exceptedFileOffset + i * packet, packet, mBuffer + i * packet);
            SetProgress(exceptedFileOffset + i * packet);
        }
        int lastPackage = tempSize % packet;
        if (lastPackage != 0) {
            PostData(exceptedFileOffset + packegeCount * packet, lastPackage,
                     mBuffer + packegeCount * packet);
        }
        uint32_t fileSize = DataConvertor::Str2U32DecHex(binInfoArray[binInfoArrayIndex].fileSize);
        if (exceptedFileOffset + tempSize >= fileSize) {
            SetProgress(fileSize);
        }
        delete []mBuffer;
        mBuffer = nullptr;
    }
}

void BurnCtrlSle::SetProgress(int size)
{
    uint32_t fileSizeSum = 0;
    for (auto it = binInfoArray.begin(); it != binInfoArray.end(); it ++) {
        fileSizeSum += DataConvertor::Str2U32DecHex(it.value().fileSize);
    }
    uint32_t offset = 0;
    for (uint32_t i = 0; i + 1 < binInfoArrayIndex; i++) {
        offset += DataConvertor::Str2U32DecHex(binInfoArray[i].fileSize);
    }
    offset += size;
    double progress = 0;
    if (fileSizeSum == 0) {
        progress = 0;
    } else {
        progress = static_cast<double>(offset) / fileSizeSum * 100; // 100为百分比
    }

    emit SignalSetProgress(progress);
}

void BurnCtrlSle::PostData(int offset, int size, PBYTE mBuffer)
{
    uint32_t bufferLen = 0;
    PBYTE replyPktBuffer = nullptr;
    uint32_t transmitDataReplyPktLen = 0;
    TransmitDataReplyPktF9 replyPkt;
    replyPkt.transmitId = mTransmitId;
    replyPkt.offset = offset;
    replyPkt.size = size;
    transmitDataReplyPktLen = sizeof(TransmitDataReplyPktF9);
    bufferLen = transmitDataReplyPktLen + size;
    replyPktBuffer = new BYTE[bufferLen];
    if (replyPktBuffer == nullptr) {
        return;
    }
    errno_t memcpyRet = memcpy_s(replyPktBuffer, bufferLen, &replyPkt, transmitDataReplyPktLen);
    if (memcpyRet != EOK) {
        return;
    }
    memcpyRet = memcpy_s(replyPktBuffer + transmitDataReplyPktLen, bufferLen - transmitDataReplyPktLen, mBuffer, size);
    if (memcpyRet != EOK) {
        return;
    }
    DIAG_CMD_ID_CONVERT_PACKET_ENCAPSULATION_FACTORY factory;
    factory.GetCmdIdPacketClass()->SetData(reinterpret_cast<PBYTE>(replyPktBuffer), bufferLen);
    PBYTE tlvData = factory.GetCmdIdPacketClass()->TLVPacket(0x01);
    SendFrame(DIAG_CMD_ID_TRANSMIT_REPLY, tlvData, factory.GetCmdIdPacketClass()->GetBufferSize());

    if (replyPktBuffer != nullptr && bufferLen > 0) {
        delete[] replyPktBuffer;
        replyPktBuffer = nullptr;
    }
}

void BurnCtrlSle::UpgRequest()
{
    DIAG_CMD_ID_CONVERT_PACKET_ENCAPSULATION_FACTORY factory;
    factory.GetCmdIdPacketClass()->SetData(nullptr, 0);
    PBYTE tlvData = factory.GetCmdIdPacketClass()->TLVPacket(0x01);
    SendFrame(DIAG_CMD_ID_UPGRADE_START, tlvData, factory.GetCmdIdPacketClass()->GetBufferSize());
}

void BurnCtrlSle::SlotOtaTimeout()
{
    otaTimer->stop();
    if (otaTimeoutCount < 5) { // 重传5次
        if (buffer == nullptr || bufferSize == 0) {
            return;
        }

        SendFrame(currentCmdId, buffer, bufferSize);
        otaTimeoutCount++;
    } else {
        QString str = tr("Board response timeout!\n");
        OutputString(str);
        otaTimeoutCount = 0;
        Close(ERR_FAILURE);
    }
}

void BurnCtrlSle::SlotReadData(uint8_t *mBuffer, uint32_t bufferLen)
{
    uint32_t len = bufferLen > MAX_BUFFER_LEN ? MAX_BUFFER_LEN : bufferLen;
    if (readBufferSize + len > MAX_BUFFER_LEN) {
        uint32_t oldLen = readBufferSize;
        uint32_t discardLen = readBufferSize + len - MAX_BUFFER_LEN;
        readBufferSize = oldLen - discardLen;
        if (memmove_s(readBuffer, MAX_BUFFER_LEN, readBuffer + discardLen, readBufferSize) != 0) {
            delete []mBuffer;
            mBuffer = nullptr;
            return;
        }
    }
    if (memcpy_s(readBuffer + readBufferSize, MAX_BUFFER_LEN - readBufferSize, mBuffer, bufferLen) != EOK) {
        delete []mBuffer;
        mBuffer = nullptr;
        return;
    }
    readBufferSize += bufferLen;
    uint32_t offset = 0;
    while (offset < readBufferSize) {
        if (readBuffer[offset] == 0x1f) {
            if (offset == 0 || memmove_s(readBuffer, MAX_BUFFER_LEN,
                                         readBuffer + offset, readBufferSize - offset) == 0) {
                readBufferSize -= offset;
                offset = 0;
            }
            usbPacket.Init(readBuffer, readBufferSize);
            if (usbPacket.CheckCrc()) {
                ReadDataHandle(offset);
            } else {
                offset++;
            }
        } else {
            offset++;
        }
    }
    delete []mBuffer;
    mBuffer = nullptr;
}

void BurnCtrlSle::ReadDataHandle(uint32_t &offset)
{
    PayloadBuffer *payloadBuffer = usbPacket.GetReadPayloadBuffer();
    uint32_t payloadBufferSize = usbPacket.GerReadPayloadBufferSize();
    if (payloadBufferSize >= PAYLOAD_BUFFER_SIZE) {
        offset++;
    } else {
        int error = ProcessReceiveData(payloadBuffer);
        if (error == ERR_SOP_SUCCESS &&
            memmove_s(readBuffer, MAX_BUFFER_LEN, readBuffer + payloadBufferSize,
                      readBufferSize - payloadBufferSize) == 0) {
            readBufferSize -= payloadBufferSize;
        } else {
            offset++;
        }
    }
}

int BurnCtrlSle::ProcessReceiveData(PayloadBuffer *&payloadBuffer)
{
    int ret = ERR_SOP_SUCCESS;
    if (payloadBuffer->commandId == 0x01 && payloadBuffer->serverId == 0x01) {
        QVector<Tlv> tlvVector = usbPacket.GetTlvVec(usbPacket.GetData(), usbPacket.GetDataSize());
        ret = ProcessACKCheck(tlvVector);
        if (ret == ERR_SOP_SUCCESS) {
            StartSearch();
        } else {
            QString str = tr("Enable Sle unsuccessfully!\n");
            OutputString(str);
            Close(ERR_COM_INVALID);
        }
    } else if (payloadBuffer->commandId == 0x0D && payloadBuffer->serverId == 0x01) {
        QVector<Tlv> tlvVector = usbPacket.GetTlvVec(usbPacket.GetData(), usbPacket.GetDataSize());
        ret = ProcessACKCheck(tlvVector);
        if (ret != ERR_SOP_SUCCESS) {
            QString str = tr("Search device unsuccessfully!\n");
            OutputString(str);
            Close(ERR_SEARCH_DEVICE_FAIL);
        } else {
            if (isOneTimeBurn) {
                ConnectServer(reinterpret_cast<WPARAM>(&sleDeviceInfo), sizeof(sleDeviceInfo));
            }
        }
    } else if (payloadBuffer->commandId == 0x0C && payloadBuffer->serverId == 0x01) {
        QVector<Tlv> tlvVector = usbPacket.GetTlvVec(usbPacket.GetData(), usbPacket.GetDataSize());
        ret = DeviceScanResultsHandler(tlvVector);
    } else {
        ret = ProcessReceiveDataAdd(payloadBuffer);
    }
    return ret;
}

int BurnCtrlSle::ProcessReceiveDataAdd(PayloadBuffer *&payloadBuffer)
{
    int ret = ERR_SOP_SUCCESS;
    if (payloadBuffer->commandId == 0x01 && payloadBuffer->serverId == 0x02) {
        QVector<Tlv> tlvVector = usbPacket.GetTlvVec(usbPacket.GetData(), usbPacket.GetDataSize());
        ret = ProcessACKCheck(tlvVector);
        if (ret == ERR_SOP_SUCCESS) {
            QString str = tr("Device connected successfully!\n");
            OutputString(str);
            emit SignalConnectResult(true);
            if (isOneTimeBurn) {
                StartBurn();
            }
        } else {
            QString str = tr("Device connected unsuccessfully!\n");
            OutputString(str);
            emit SignalConnectResult(false);
            Close(ERR_DEVICE_NOT_CONNECTED);
        }
    } else if (payloadBuffer->commandId == 0x07 && payloadBuffer->serverId == 0x03) {
        QVector<Tlv> tlvVector = usbPacket.GetTlvVec(usbPacket.GetData(), usbPacket.GetDataSize());
        ret = UpgradeRequestHandler(tlvVector);
    } else if (payloadBuffer->commandId == 0x02 && payloadBuffer->serverId == 0x02) {
        QVector<Tlv> tlvVector = usbPacket.GetTlvVec(usbPacket.GetData(), usbPacket.GetDataSize());
        ret = ProcessACKCheck(tlvVector);
        if (ret == ERR_SOP_SUCCESS) {
            QString str = tr("Device disconnected successfully!\n");
            OutputString(str);
            emit SignalConnectResult(false);
        } else {
            QString str = tr("Device disconnected unsuccessfully!\n");
            OutputString(str);
            emit SignalConnectResult(true);
        }
    }
    return ret;
}

int BurnCtrlSle::ProcessACKCheck(const QVector<Tlv> &tlvVector) const
{
    if (tlvVector.size() == 1 && tlvVector[0].type == 0x7f && tlvVector[0].lenth == 0x01) {
        uint8_t val = *(reinterpret_cast<uint8_t *>(tlvVector[0].data));
        if (val == static_cast<uint8_t>(SleAckError::SLE_ACK_SUCCESS)) {
            return ERR_SOP_SUCCESS;
        } else {
            return ERR_SOP_FAILURE;
        }
    }
    return ERR_SOP_FAILURE;
}

int BurnCtrlSle::UpgradeRequestHandler(const QVector<Tlv> &tlvVector)
{
    int ret = ERR_SOP_SUCCESS;
    for (int i = 0; i < tlvVector.size(); i++) {
        if (tlvVector[i].type == 0x7f && tlvVector[i].lenth == 0x01) {
            uint8_t val = *(reinterpret_cast<uint8_t *>(tlvVector[0].data));
            if (val == static_cast<uint8_t>(SleAckError::SLE_ACK_SUCCESS)) {
                ret = ERR_SOP_SUCCESS;
            } else {
                // to do 错误
            }
        } else if (tlvVector[i].type == 0x06) {
            BurnToolCommon::MSP_MUX_PACKET_HEAD_STRU_FACTORY headFactory;
            BurnToolCommon::MSP_MUX_PACKET_HEAD_STRU_CLASS *pstDiagHead = headFactory.GetItem();
            pstDiagHead->Init(tlvVector[i].data, tlvVector[i].lenth);
            PBYTE data = pstDiagHead->GetData();
            uint32_t dataSize = pstDiagHead->GetPacketDataSize();
            BurnToolCommon::MSP_DIAG_HEAD_REQ_STRU_FACTORY factory;
            BurnToolCommon::MSP_DIAG_HEAD_REQ_STRU_CLASS *pstDiagHeadReq = factory.GetItem();
            pstDiagHeadReq->Init(data, dataSize);
            data = pstDiagHeadReq->GetData();
            dataSize = pstDiagHeadReq->GetPacketDataSize();
            if (data == nullptr || dataSize == 0 || (!pstDiagHead->CheckCrc())) {
                // to do 错误
                ret = ERR_SOP_FAILURE;
            }
            ret = OtaInfoHandler(pstDiagHead->GetCmdId(), data, dataSize);
            delete pstDiagHead;
            pstDiagHead = nullptr;
        }
    }

    return ret;
}

int BurnCtrlSle::DeviceScanResultsHandler(const QVector<Tlv> &tlvVector)
{
    QString address = "";
    for (int i = 0; i < tlvVector.size(); i++) {
        address.clear();
        SleDeviceInfo info;
        if (tlvVector[i].type == 0x03 && tlvVector[i].lenth == 6) { // 6
            for (int j = 0; j < tlvVector[i].lenth; j++) {
                info.addr[j] = tlvVector[i].data[j];
            }
        } else if (tlvVector[i].type == 0x02 && tlvVector[i].lenth == 1) {
            for (int j = 0; j < tlvVector[i].lenth; j++) {
                info.addrType = tlvVector[i].data[j];
            }
        }
        PartDeviceScanResultsHandler(info);
    }
    return ERR_SOP_SUCCESS;
}

void BurnCtrlSle::PartDeviceScanResultsHandler(SleDeviceInfo info)
{
    bool flag = false;
    for (auto it = vecInfo.begin(); it != vecInfo.end(); it++) {
        int index = 0;
        for (; index < 6; index++) { // 6
            if (it->addr[index] != info.addr[index]) {
                break;
            }
        }
        if (index == 6) { // 6
            flag = true;
            break;
        }
    }

    if (!flag) {
        vecInfo.push_back(info);
        emit SignalSetAddress(vecInfo);
    }
}

int BurnCtrlSle::OtaInfoHandler(uint32_t cmdId, PBYTE pBuffer, uint32_t ulBufferSize)
{
    int ret = ERR_SOP_FAILURE;
    if (pBuffer == nullptr || ulBufferSize == 0) {
        return ret;
    }
    otaTimeoutCount = 0;
    if (otaTimer != nullptr) {
        otaTimer->stop();
    }
    if (isStop) {
        return ret;
    }
    if (cmdId == DIAG_CMD_ID_TRANSMIT_REQUEST) {
        ret = TransmitReqHandler(pBuffer, ulBufferSize);
    } else if (cmdId == DIAG_CMD_ID_TRANSMIT_NOTIFY) {
        ret = TransmitStateNotifyHandler(pBuffer, ulBufferSize);
    } else if (cmdId == DIAG_CMD_ID_UPGRADE_STATUS) {
        ret = UpgradeStatusHandler(pBuffer, ulBufferSize);
    } else if (cmdId == DIAG_CMD_ID_UPGRADE_PREPARE) {
        ret = UpgradePrepareHandler(pBuffer, ulBufferSize);
    } else if (cmdId == DIAG_CMD_ID_UPGRADE_REQUEST) {
        ret = UpgradeRequestHandler(pBuffer, ulBufferSize);
    }
    return ret;
}

void BurnCtrlSle::SaveBuffer(uint32_t cmdId, PBYTE pBuffer, uint32_t ulBufferSize)
{
    if (pBuffer == nullptr || ulBufferSize == 0 || buffer == nullptr) {
        return;
    }
    currentCmdId = cmdId;
    PBYTE tempBuffer = new BYTE[ulBufferSize];
    if (tempBuffer == nullptr) {
        delete []tempBuffer;
        tempBuffer = nullptr;
        return;
    }
    errno_t memsetRet = memset_s(tempBuffer, ulBufferSize, 0, ulBufferSize);
    if (memsetRet != EOK) {
        delete []tempBuffer;
        tempBuffer = nullptr;
        return;
    }
    errno_t memcpyRet = memcpy_s(tempBuffer, ulBufferSize, pBuffer, ulBufferSize);
    if (memcpyRet != EOK) {
        delete []tempBuffer;
        tempBuffer = nullptr;
        return;
    }
    memsetRet = memset_s(buffer, BUFFER_SIZE_MAX, 0, BUFFER_SIZE_MAX);
    if (memsetRet != EOK) {
        delete []tempBuffer;
        tempBuffer = nullptr;
        return;
    }
    memcpyRet = memcpy_s(buffer, BUFFER_SIZE_MAX, tempBuffer, ulBufferSize);
    if (memcpyRet != EOK) {
        delete []tempBuffer;
        tempBuffer = nullptr;
        return;
    }
    bufferSize = ulBufferSize;
    delete []tempBuffer;
    tempBuffer = nullptr;
}

int BurnCtrlSle::UpgradeStatusHandler(PBYTE pBuffer, uint32_t ulBufferSize)
{
    int ret = ERR_SOP_SUCCESS;
    DIAG_CMD_ID_CONVERT_PACKET_ENCAPSULATION_FACTORY factory;
    factory.GetCmdIdPacketClass()->Init(pBuffer, ulBufferSize);
    PBYTE tempBuffer = factory.GetCmdIdPacketClass()->GetData();
    uint32_t tempBufferSize = factory.GetCmdIdPacketClass()->GetDataSize();
    if (tempBuffer == nullptr || tempBufferSize < sizeof (UpgInfoAck)) {
        return ERR_SOP_FAILURE;
    }
    UpgInfoAck *statusValue = reinterpret_cast<UpgInfoAck*>(tempBuffer);
    if (statusValue->type == static_cast<uint16_t>(UpgradeTypeT::UPG_INFO_TYPE_PERMIT)) {
        if (statusValue->size < sizeof (uint32_t)) {
            return ERR_SOP_FAILURE;
        }

        uint32_t retValue = *(reinterpret_cast<uint32_t*>(statusValue->info));
        if (retValue == ERR_SOP_SUCCESS) {
            UpgPrepare();
        } else {
            // to do error
            return ERR_SOP_FAILURE;
        }
    }

    return ret;
}

int BurnCtrlSle::UpgradePrepareHandler(PBYTE pBuffer, uint32_t ulBufferSize)
{
    DIAG_CMD_ID_CONVERT_PACKET_ENCAPSULATION_FACTORY factory;
    factory.GetCmdIdPacketClass()->Init(pBuffer, ulBufferSize);
    PBYTE tempBuffer = factory.GetCmdIdPacketClass()->GetData();
    uint32_t tempBufferSize = factory.GetCmdIdPacketClass()->GetDataSize();
    if (tempBuffer == nullptr || tempBufferSize < sizeof (uint32_t)) {
        return ERR_SOP_FAILURE;
    }
    uint32_t *statusValue = reinterpret_cast<uint32_t*>(tempBuffer);
    if (*statusValue == ERR_SOP_SUCCESS) {
        UpgTransmitStart();
    } else {
        // to do error
        return ERR_SOP_FAILURE;
    }

    return ERR_SOP_SUCCESS;
}

int BurnCtrlSle::UpgradeRequestHandler(PBYTE pBuffer, uint32_t ulBufferSize) const
{
    DIAG_CMD_ID_CONVERT_PACKET_ENCAPSULATION_FACTORY factory;
    factory.GetCmdIdPacketClass()->Init(pBuffer, ulBufferSize);
    PBYTE packetData = factory.GetCmdIdPacketClass()->GetData();
    uint32_t packetDataSize = factory.GetCmdIdPacketClass()->GetDataSize();
    if (packetData == nullptr || packetDataSize < sizeof (uint32_t)) {
        return ERR_SOP_FAILURE;
    }
    uint32_t *statusValue = reinterpret_cast<uint32_t*>(packetData);
    if (*statusValue == ERR_SOP_SUCCESS) {
        return ERR_SOP_SUCCESS;
    } else {
        // to do error
        return ERR_SOP_FAILURE;
    }
    return ERR_SOP_SUCCESS;
}

int BurnCtrlSle::TransmitReqHandler(PBYTE pBuffer, uint32_t ulBufferSize)
{
    DIAG_CMD_ID_CONVERT_PACKET_ENCAPSULATION_FACTORY factory;
    factory.GetCmdIdPacketClass()->Init(pBuffer, ulBufferSize);
    PBYTE tempBuffer = factory.GetCmdIdPacketClass()->GetData();
    uint32_t tempBufferSize = factory.GetCmdIdPacketClass()->GetDataSize();
    if (tempBuffer == nullptr || tempBufferSize < sizeof (TransmitDataRequestItem) + sizeof (TransmitDataRequestPkt)) {
        return ERR_SOP_FAILURE;
    }
    TransmitDataRequestPkt *reqPkt = reinterpret_cast<TransmitDataRequestPkt*>(tempBuffer);
    if (mTransmitId != reqPkt->transmitId) {
        return ERR_SOP_FAILURE;
    }
    uint32_t count = reqPkt->cnt;
    QVector<TransmitDataRequestItem> items;
    for (uint32_t i = 0; i < count; i++) {
        TransmitDataRequestItem item;
        if (memcpy_s(reinterpret_cast<PBYTE>(&item), sizeof (TransmitDataRequestItem),
                     tempBuffer + sizeof(TransmitDataRequestPkt) + sizeof (TransmitDataRequestItem) * i,
                     sizeof (TransmitDataRequestItem)) != 0) {
            continue;
        }
        items.append(item);
    }
    UpgTransmitReply(items);
    return ERR_SOP_SUCCESS;
}

int BurnCtrlSle::TransmitStateNotifyHandler(PBYTE pBuffer, uint32_t ulBufferSize)
{
    DIAG_CMD_ID_CONVERT_PACKET_ENCAPSULATION_FACTORY factory;
    factory.GetCmdIdPacketClass()->Init(pBuffer, ulBufferSize);
    PBYTE tempBuffer = factory.GetCmdIdPacketClass()->GetData();
    uint32_t tempBufferSize = factory.GetCmdIdPacketClass()->GetDataSize();
    if (!tempBuffer || tempBufferSize < sizeof(TransmitStateNotifyPkt)) {
        return ERR_SOP_FAILURE;
    }
    TransmitStateNotifyPkt *notifyPkt = reinterpret_cast<TransmitStateNotifyPkt*>(tempBuffer);
    if (mTransmitId != notifyPkt->transmitId) {
        return ERR_SOP_FAILURE;
    }
    uint32_t ret = 0;
    if (notifyPkt->stateCode ==
        static_cast<uint32_t>(TransmitStateNotifyCode::TRANSMIT_STATE_NOTIFY_FILE_SYSTEM_IS_AVNORMAL)) {
        return ERR_SOP_SUCCESS;
    } else {
        // 其他异常场景
        ret = notifyPkt->stateCode;
    }
    mTransmitId = 0;
    QString str = "";
    if (binInfoArray[binInfoArrayIndex].fileName.isEmpty()) {
        str = binInfoArray[binInfoArrayIndex].path;
    } else {
        str = binInfoArray[binInfoArrayIndex].fileName;
    }
    str += tr(" upload successfully\n");
    binInfoArrayIndex++;
    if (binInfoArrayIndex >= static_cast<uint32_t>(binInfoArray.size())) {
        UpgRequest();
        OutputString(IDS_STRING_32879 + "\n");
        QString str2 = tr("Upgrading, do not power off! Please wait...\n");
        OutputString(str2);
        OutputString(IDS_STRING_32879 + "\n");
        Sleep(8000); // 8000
        str2 = tr("Upgrade successfully!\n");
        OutputString(str2);
        emit SignalSetProgress(100); // 成功时进度条设置为100%
        Close(0);
    } else {
        UpgPrepare();
    }
    return ERR_SOP_SUCCESS;
}

bool BurnCtrlSle::IsOpen() const
{
    if (usbPort != nullptr) {
        return usbPort->IsOpen();
    }
    return false;
}

void BurnCtrlSle::OutputString(QString editStr)
{
    emit SignalInsertPlainText(editStr);
}

void BurnCtrlSle::SetIsStop()
{
    isStop = true;
}

void BurnCtrlSle::SetOneTimeBurnFlag(bool isOneTime)
{
    this->isOneTimeBurn = isOneTime;
}

void BurnCtrlSle::SetDeviceInfo(SleDeviceInfo sle)
{
    sleDeviceInfo = sle;
}

void BurnCtrlSle::Close(int result) const
{
    if (isOneTimeBurn) {
        Global::CloseApp(result);
    }
}
